<?php

namespace App\Console\Commands;

use App\Models\Bi\BiOrder;
use App\Models\Bi\BiRefundOrder;
use App\Models\Bi\RefundLog;
use App\Models\Order;
use App\Models\RefundOrder;
use App\Models\StoreGoods;
use App\Services\Easypay\Incoming\Config;
use App\Services\PrintSqlService;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Schema;

class MoveStoreCommand extends Command
{
    protected $signature = 'move:store';
    protected $description = 'Export large datasets to CSV with memory optimization';

    public function handle()
    {
        PrintSqlService::listen();

        $yields = Order::query()
            ->where("created_at", ">=", "2025-07-01 00:00:00")
            ->where("store_id", "202542413176810423")
            ->whereIn("pay_status", [1, 6])
            ->get();
//        select  *  from  bi_bill_logs where store_pid="202561017616015588" and `day`>="2025-06-01 00:00:00"  limit 100
// select  *  from  bi_bill_logs where store_pid="202541175819806580" and `day`>="2025-06-01 00:00:00" limit 100;  -- 只处理6月+7月
//select *  from bi_bills where store_pid="202561017616015588" and `day`>="2025-06-01 00:00:00"
//select *  from bi_bills where store_pid="202541175819806580" and `day`>="2025-06-01 00:00:00"
        foreach ($yields as $order) {
            $redis = Redis::connection('amqpQueue');
            $data = [
                "out_trade_no" => $order->out_trade_no,
                "type" => 1,
                "from" => "pay",
            ];
            $redis->rPush("payListener", json_encode($data));
            if ($order->pay_status == 6) {
                RefundLog::query()->where("out_trade_no",$order->out_trade_no)->delete();
                $refund = RefundOrder::query()->where("out_trade_no", $order->out_trade_no)->first();
                $data = [
                    "out_trade_no" => $order->out_trade_no,
                    "refund_no" => empty($refund) ? "" : $refund->refund_no,
                    "type" => 2,
                    "from" => "pay",
                ];
                $redis->rPush("payListener", json_encode($data));
            }
        }
        dd("投递数据，重新制作账单成功");
        dd();
        PrintSqlService::listen();
        dd(Schema::connection("bi")->hasTable("orders_202504"));
        $this->exportToFileWithCursor();
        dd();
        // 提高内存限制并取消执行时间限制
        ini_set('memory_limit', '1024M');
        set_time_limit(0);

        $fileName = "订单导出_" . date("Y-m-d") . "_" . time() . ".csv";
        $filePath = public_path("/uploads/csv/" . date("Y/md") . "/");

        // 创建目录（存在则跳过）
        if (!is_dir($filePath)) {
            mkdir($filePath, 0777, true);
        }

        // 初始化CSV文件
        $this->initCsvFile($filePath . $fileName);

        // 获取查询构建器
        $query = BiOrder::query()
            ->from("orders_202505")
            ->where("created_at", ">=", "2025-05-01 00:00:00");

        // 执行流式导出
        $this->streamExportToCsv($query, $filePath . $fileName);
    }

    private function initCsvFile(string $fullPath): void
    {
        $fp = fopen($fullPath, 'w');
        fwrite($fp, "\xEF\xBB\xBF"); // UTF-8 BOM
        fputcsv($fp, [
            '门店ID', '门店名称', '收银员', '订单号',
            '订单金额', '退款金额', '费率', '手续费',
            '支付方式', '支付状态', '付款时间', '通道',
            '备注', '退款时间'
        ]);
        fclose($fp);
    }

    private function streamExportToCsv($query, string $fullPath): void
    {
        $fp = fopen($fullPath, 'a');

        // 使用游标逐行处理
        foreach ($query->cursor() as $index => $record) {
            // 立即写入单行数据（不缓冲）
            fputcsv($fp, [
                $record->store_id,
                $record->store_name,
                $record->merchant_name ?? "",
                $record->out_trade_no ?? "",
                $record->total_amount ?? "",
                $record->refund_amount ?? "",
                $record->rate,
                $record->fee_amount,
                $record->ways_type_desc,
                $record->pay_status_desc,
                $record->pay_time,
                $record->company,
                "",
                $record->refund_time ?? "",
            ]);

            // 每1000行清理一次内存
            if ($index % 1000 === 0) {
                fflush($fp);
                gc_collect_cycles();
            }
            unset($record);
        }

        fclose($fp);
    }


    public function exportToFileWithCursor()
    {
        set_time_limit(0);
        ini_set('memory_limit', '216M');
        $filename = storage_path('app/exports/orders_' . date('Ymd_His') . '.csv');
        // 确保目录存在
        if (!file_exists(dirname($filename))) {
            mkdir(dirname($filename), 0755, true);
        }
        $file = fopen($filename, 'w');
        fwrite($file, "\xEF\xBB\xBF"); // UTF-8 BOM
        // 标题行
        fputcsv($file, ['订单号', '门店ID', '门店名称', '收银员', '订单金额', '退款金额', '费率', '手续费', '支付方式', '支付状态', '付款时间', '通道']);
        // 使用cursor()处理
        $connection = DB::connection("bi");
        $connection->getPdo()->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
        $orders = $connection->table("orders_202505")
//        BiOrder::query()->from("orders_202505")
            ->select(['id', 'out_trade_no', "store_id", "store_name", "merchant_name", "total_amount", "refund_amount", "rate", "fee_amount", "ways_type_desc", "pay_status_desc", "pay_time", "company"])
            ->leftJoin("")
            ->cursor();
        $counter = 0;
        foreach ($orders as $order) {
            fputcsv($file, [
                $order->out_trade_no,
                $order->store_id,
                $order->store_name,
                $order->merchant_name,
                $order->total_amount,
                $order->refund_amount,
                $order->rate,
                $order->fee_amount,
                $order->ways_type_desc,
                $order->pay_status_desc,
                $order->pay_time,
                $order->company
            ]);
            // 每5000行刷新一次文件缓冲
            if (++$counter % 1000 === 0) {
                fflush($file);
//                ob_flush();
                flush();
                gc_collect_cycles();
                // 可选：记录进度
                Log::info("Processed {$counter} records");
            }
            unset($order);
        }
        fclose($file);
        return response()->download($filename)->deleteFileAfterSend(true);
    }
}